package com.rzico.sbl.other;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.SparseArray;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.DrawableImageViewTarget;

import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;


/**
 * 详细使用：
 * <a href="https://blog.csdn.net/qian520ao/article/details/76167193">点击查看</a>
 */
public abstract class LinearNormalDecoration extends RecyclerView.ItemDecoration {

    private final Paint mHeaderTxtPaint;
    private final Paint mHeaderContentPaint;

    protected int headerHeight = 136; //头部高度
    protected int footerHeight = 40;  //底部高度
    private int textPaddingLeft = 50; //头部文字左边距
    private int textSize = 50;
    private int textColor = 0xff333333;
    private int headerContentColor = 0xfff8f8f8;
    private final float txtYAxis;
    private RecyclerView mRecyclerView;
    private boolean isInitHeight = false;

    private final Map<Integer, View> headViewMap = new HashMap<>();
    // 图标集合
    private final Map<String, Drawable> imgDrawableMap = new HashMap<>();
    // 记录每个头部和悬浮头部的坐标信息【用于点击事件】
    private final SparseArray<Integer> stickyHeaderPosArray = new SparseArray<>();
    private GestureDetector gestureDetector;
    private OnDecorationHeadDraw headerDrawEvent;

    public LinearNormalDecoration() {
        mHeaderTxtPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mHeaderTxtPaint.setColor(textColor);
        mHeaderTxtPaint.setTextSize(textSize);
        mHeaderTxtPaint.setTextAlign(Paint.Align.LEFT);

        mHeaderContentPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mHeaderContentPaint.setColor(headerContentColor);
        Paint.FontMetrics fontMetrics = mHeaderTxtPaint.getFontMetrics();
        float total = -fontMetrics.ascent + fontMetrics.descent;
        txtYAxis = total / 2 - fontMetrics.descent;
    }

    /**
     * 先调用getItemOffsets再调用onDraw
     */
    @Override
    public void getItemOffsets(
            @NotNull Rect outRect,
            @NotNull View itemView,
            @NotNull RecyclerView parent,
            @NotNull RecyclerView.State state
    ) {
        super.getItemOffsets(outRect, itemView, parent, state);

        if (mRecyclerView == null) mRecyclerView = parent;

        if (headerDrawEvent != null && !isInitHeight) {
            View headerView = headerDrawEvent.getHeaderView(0);
            headerView.measure(
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            );
            headerHeight = headerView.getMeasuredHeight();
            isInitHeight = true;
        }

        // 我们为每个不同头部名称的第一个item设置头部高度
        int pos = parent.getChildAdapterPosition(itemView); //获取当前itemView的位置
        String curHeaderName = getHeaderName(pos);          //根据pos获取要悬浮的头部名

        if (parent.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager manger = (LinearLayoutManager) parent.getLayoutManager();
            int itemCount = manger.getItemCount();
            if (curHeaderName != null) {
                if (pos == 0
                        || !curHeaderName.equals(getHeaderName(pos - 1))) {
                    // 如果当前位置为0，或者与上一个item头部名不同的，都腾出头部空间
                    outRect.top = headerHeight; //设置itemView PaddingTop的距离
                }

                if (pos == itemCount - 1
                        || curHeaderName.equals(getHeaderName(pos + 1))) {
                    outRect.bottom = footerHeight; //设置itemView PaddingBottom的距离
                }
            }
        }
    }

    public abstract String getHeaderName(int pos);

    @Override
    public void onDrawOver(
            @NotNull Canvas canvas,
            @NotNull RecyclerView recyclerView,
            @NotNull RecyclerView.State state
    ) {
        super.onDrawOver(canvas, recyclerView, state);

        if (mRecyclerView == null) mRecyclerView = recyclerView;

        if (gestureDetector == null) {
            gestureDetector = new GestureDetector(recyclerView.getContext(), gestureListener);
            recyclerView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
        }

        stickyHeaderPosArray.clear();

        int childCount = recyclerView.getChildCount(); //获取屏幕上可见的item数量
        int left = recyclerView.getLeft() + recyclerView.getPaddingLeft();
        int right = recyclerView.getRight() - recyclerView.getPaddingRight();

        String firstHeaderName = null;
        int firstPos = 0;
        int translateTop = 0;//绘制悬浮头部的偏移量
        /*for循环里面绘制每个分组的头部*/
        for (int i = 0; i < childCount; i++) {
            View childView = recyclerView.getChildAt(i);
            int pos = recyclerView.getChildAdapterPosition(childView); //获取当前view在Adapter里的pos
            String curHeaderName = getHeaderName(pos);                 //根据pos获取要悬浮的头部名
            if (i == 0) {
                firstHeaderName = curHeaderName;
                firstPos = pos;
            }
            if (curHeaderName == null)
                continue;//如果headerName为空，跳过此次循环

            int viewTop = childView.getTop() + recyclerView.getPaddingTop();
            if (pos == 0 || !curHeaderName.equals(getHeaderName(pos - 1))) {//如果当前位置为0，或者与上一个item头部名不同的，都腾出头部空间
                //绘制每个组头【奥拓上头的a(奥迪上头就不用绘制a),本田上头的b】
                if (headerDrawEvent != null) {
                    View headerView;
                    if (headViewMap.get(pos) == null) {
                        headerView = headerDrawEvent.getHeaderView(pos);
                        headerView.measure(
                                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
                        );
                        headerView.setDrawingCacheEnabled(true);
                        headerView.layout(0, 0, right, headerHeight); //布局layout
                        headViewMap.put(pos, headerView);
                    } else {
                        headerView = headViewMap.get(pos);
                    }

                    if (headerView != null) {
                        canvas.drawBitmap(
                                headerView.getDrawingCache(),
                                left,
                                viewTop - headerHeight,
                                null
                        );
                    }
                } else {
                    canvas.drawRect(left, viewTop - headerHeight, right, viewTop, mHeaderContentPaint);
                    canvas.drawText(
                            curHeaderName,
                            left + textPaddingLeft,
                            viewTop - headerHeight / 2f + txtYAxis,
                            mHeaderTxtPaint
                    );
                }

                if (headerHeight < viewTop && viewTop <= 2 * headerHeight) { //此判断是刚好2个头部碰撞，悬浮头部就要偏移
                    translateTop = viewTop - 2 * headerHeight;
                }

                stickyHeaderPosArray.put(pos, viewTop); //将头部信息放进array
            }
        }

        if (firstHeaderName == null) return;

        canvas.save();
        canvas.translate(0, translateTop);

        if (headerDrawEvent != null) {
            View headerView;
            if (headViewMap.get(firstPos) == null) {
                headerView = headerDrawEvent.getHeaderView(firstPos);
                headerView.measure(
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                headerView.setDrawingCacheEnabled(true);
                headerView.layout(0, 0, right, headerHeight);//布局layout
                headViewMap.put(firstPos, headerView);
            } else {
                headerView = headViewMap.get(firstPos);
            }

            if (headerView != null) {
                canvas.drawBitmap(
                        headerView.getDrawingCache(),
                        left,
                        0,
                        null
                );
            }
        } else {
            // 绘制悬浮的头部
            canvas.drawRect(left, 0, right, headerHeight, mHeaderContentPaint);
            canvas.drawText(
                    firstHeaderName,
                    left + textPaddingLeft,
                    headerHeight / 2f + txtYAxis,
                    mHeaderTxtPaint
            );
        }
        canvas.restore();
    }

    public interface OnHeaderClickListener {
        void headerClick(int pos);
    }

    private OnHeaderClickListener headerClickEvent;

    public void setOnHeaderClickListener(OnHeaderClickListener headerClickListener) {
        this.headerClickEvent = headerClickListener;
    }

    private final GestureDetector.OnGestureListener gestureListener =
            new GestureDetector.OnGestureListener() {
                @Override
                public boolean onDown(MotionEvent e) {
                    return false;
                }

                @Override
                public void onShowPress(MotionEvent e) {
                }

                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    for (int i = 0; i < stickyHeaderPosArray.size(); i++) {
                        int value = stickyHeaderPosArray.valueAt(i);
                        float y = e.getY();
                        if (value - headerHeight <= y && y <= value) {//如果点击到分组头
                            if (headerClickEvent != null) {
                                headerClickEvent.headerClick(stickyHeaderPosArray.keyAt(i));
                            }
                            return true;
                        }
                    }
                    return false;
                }

                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                    return false;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                }

                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                    return false;
                }
            };

    public interface OnDecorationHeadDraw {
        View getHeaderView(int pos);
    }

    /**
     * 只是用来绘制，不能做其他处理/点击事件等
     */
    public void setOnDecorationHeadDraw(OnDecorationHeadDraw decorationHeadDraw) {
        this.headerDrawEvent = decorationHeadDraw;
    }

    public void loadImage(final String url, final int pos, ImageView imageView) {
        if (getImg(url) != null) {
            imageView.setImageDrawable(getImg(url));
        } else {
            Glide.with(mRecyclerView.getContext())
                    .load(url)
                    .into(new DrawableImageViewTarget(imageView) {
                        @Override
                        protected void setResource(@Nullable Drawable resource) {
                            headViewMap.remove(pos); //删除，重新更新
                            imgDrawableMap.put(url, resource);
                            mRecyclerView.postInvalidate();
                        }
                    });
        }

    }

    private Drawable getImg(String url) {
        return imgDrawableMap.get(url);
    }

    public void onDestory() {
        headViewMap.clear();
        imgDrawableMap.clear();
        stickyHeaderPosArray.clear();
        mRecyclerView = null;
        setOnHeaderClickListener(null);
        setOnDecorationHeadDraw(null);
    }

    /**
     * 设置头部分割高度
     */
    public void setHeaderHeight(int headerHeight) {
        this.headerHeight = headerHeight;
    }

    /**
     * 设置底部分割高度
     */
    public void setFooterHeight(int footerHeight) {
        this.footerHeight = footerHeight;
    }

    /**
     * 设置分割背景色
     */
    public void setHeaderContentColor(int headerContentColor) {
        this.headerContentColor = headerContentColor;
        this.mHeaderContentPaint.setColor(headerContentColor);
    }

    /**
     * 设置文本左边距
     */
    public void setTextPaddingLeft(int textPaddingLeft) {
        this.textPaddingLeft = textPaddingLeft;
    }

    /**
     * 设置文本大小
     */
    public void setTextSize(int textSize) {
        this.textSize = textSize;
        this.mHeaderTxtPaint.setTextSize(textSize);
    }

    /**
     * 设置文本颜色
     */
    public void setTextColor(int textColor) {
        this.textColor = textColor;
        this.mHeaderTxtPaint.setColor(textColor);
    }

}
